#include "cartographer/common/task.h"

namespace cartographer
{
    namespace common
    {
        Task::~Task()
        {
            // TODO(gaschler): Relax some checks after testing.
            if (state_ != NEW && state_ != COMPLETED)
            {
                LOG(WARNING) << "Delete Task between dispatch and completion.";
            }
        }

        Task::State Task::GetState()
        {
            absl::MutexLock locker(&mutex_);
            return state_;
        }

        void Task::SetWorkItem(const WorkItem &work_item)
        {
            absl::MutexLock locker(&mutex_);
            CHECK_EQ(state_, NEW);
            work_item_ = work_item;
        }

        // [弱指针] 可从一个shared_ptr或者另一个weak_ptr对象构造, 获得资源的观测权
        // 但weak_ptr没有共享资源, 它的构造不会引起指针引用计数的增加.
        // 同样, 在weak_ptr析构时也不会导致引用计数的减少, 它只是一个静静地观察者.
        // weak_ptr没有重载operator*和->, 因为它不共享指针, 不能操作资源, 这是它弱的原因
        // 可使用成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 从而操作资源.

        void Task::AddDependency(std::weak_ptr<Task> dependency)
        {
            std::shared_ptr<Task> shared_dependency;
            {
                absl::MutexLock locker(&mutex_);
                CHECK_EQ(state_, NEW);
                if ((shared_dependency = dependency.lock()))
                {
                    ++uncompleted_dependencies_;
                }
            }
            if (shared_dependency)
            {
                shared_dependency->AddDependentTask(this);
            }
        }

        void Task::SetThreadPool(ThreadPoolInterface *thread_pool)
        {
            absl::MutexLock locker(&mutex_);
            CHECK_EQ(state_, NEW);
            state_ = DISPATCHED;
            thread_pool_to_notify_ = thread_pool;
            if (uncompleted_dependencies_ == 0)
            {
                state_ = DEPENDENCIES_COMPLETED;
                CHECK(thread_pool_to_notify_);
                thread_pool_to_notify_->NotifyDependenciesCompleted(this);
            }
        }

        void Task::AddDependentTask(Task *dependent_task)
        {
            absl::MutexLock locker(&mutex_);
            if (state_ == COMPLETED)
            {
                dependent_task->OnDependenyCompleted();
                return;
            }
            bool inserted = dependent_tasks_.insert(dependent_task).second;
            CHECK(inserted) << "Given dependency is already a dependency.";
        }

        // 该任务依赖的任务全部执行完再执行自身
        void Task::OnDependenyCompleted()
        {
            absl::MutexLock locker(&mutex_);
            CHECK(state_ == NEW || state_ == DISPATCHED);
            --uncompleted_dependencies_;
            if (uncompleted_dependencies_ == 0 && state_ == DISPATCHED)
            {
                state_ = DEPENDENCIES_COMPLETED;
                CHECK(thread_pool_to_notify_);
                thread_pool_to_notify_->NotifyDependenciesCompleted(this);
            }
        }

        void Task::Execute()
        {
            {
                absl::MutexLock locker(&mutex_);
                CHECK_EQ(state_, DEPENDENCIES_COMPLETED);
                state_ = RUNNING;
            }
            // Execute the work item.
            if (work_item_)
            {
                work_item_();
            }
            //dependent_tasks_记录的是依赖本任务的任务，故本任务结束后，通知其他任务
            absl::MutexLock locker(&mutex_);
            state_ = COMPLETED;
            for (Task *dependent_task : dependent_tasks_)
            {
                dependent_task->OnDependenyCompleted();
            }
        }

    } // namespace common
} // namespace cartographer
